package com.grm.sys.service.impl;

import com.grm.common.exception.BusinessException;
import com.grm.common.utils.ListBeanUtils;
import com.grm.common.utils.TreeUtils;
import com.grm.sys.mapper.SysDeptMapper;
import com.grm.sys.mapper.SysUserMapper;
import com.grm.sys.model.SysDept;
import com.grm.sys.model.SysPerm;
import com.grm.sys.model.SysUser;
import com.grm.sys.request.dept.SysDeptAddParam;
import com.grm.sys.request.dept.SysDeptUpdateParam;
import com.grm.sys.response.SysDeptResponse;
import com.grm.sys.service.SysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class SysDeptServiceImpl implements SysDeptService {
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public List<SysDeptResponse> tree() {
        List<SysDept> sysDeptList = sysDeptMapper.list();
        if (ObjectUtils.isNotEmpty(sysDeptList)) {
            List<SysDeptResponse> sysDeptResponseList = new ArrayList<>();
            for (SysDept sysDept : sysDeptList) {
                SysDeptResponse sysDeptResponse = sysDeptToSysDeptResponse(sysDept);
                sysDeptResponseList.add(sysDeptResponse);
            }
            return TreeUtils.getTree(sysDeptResponseList);
        }
        return new ArrayList<>();
    }

    private SysDeptResponse sysDeptToSysDeptResponse(SysDept sysDept) {
        SysDeptResponse sysDeptResponse = new SysDeptResponse();
        sysDeptResponse.setId(sysDept.getId());
        sysDeptResponse.setName(sysDept.getName());
        sysDeptResponse.setParentId(sysDept.getParentId());
        sysDeptResponse.setSort(sysDept.getSort());

        // 根据leaderId查询领导信息
        if (ObjectUtils.isNotEmpty(sysDept.getLeaderId())) {
            SysUser sysUser = sysUserMapper.queryById(sysDept.getLeaderId());
            sysDeptResponse.setLeader(sysUser);
        }
        sysDeptResponse.setRemark(sysDept.getRemark());
        sysDeptResponse.setChildren(new ArrayList<>());
        return sysDeptResponse;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void add(SysDeptAddParam sysDeptAddParam) {
        // 同一层级下不能有相同的部门名称
        SysDept dbSysDept = sysDeptMapper.queryByParentIdAndName(sysDeptAddParam.getParentId(), sysDeptAddParam.getName());
        if (dbSysDept != null) {
            throw new BusinessException("同一层级下不能有相同的部门名称!");
        }
        SysDept sysDept = sysDeptAddParamToSysDept(sysDeptAddParam);
        sysDeptMapper.add(sysDept);
    }

    private SysDept sysDeptAddParamToSysDept(SysDeptAddParam sysDeptAddParam) {
        SysDept sysDept = new SysDept();
        sysDept.setParentId(sysDeptAddParam.getParentId());
        sysDept.setName(sysDeptAddParam.getName());
        sysDept.setLeaderId(sysDeptAddParam.getLeaderId());
        sysDept.setSort(sysDeptAddParam.getSort());
        sysDept.setRemark(sysDeptAddParam.getRemark());
        return sysDept;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void update(SysDeptUpdateParam sysDeptUpdateParam) {
        SysDept dbSysDept = sysDeptMapper.queryById(sysDeptUpdateParam.getId());
        if (dbSysDept == null) {
            throw new BusinessException("部门不存在！");
        }

        SysDept sysDept2 = sysDeptMapper.queryByParentIdAndName(sysDeptUpdateParam.getParentId(), sysDeptUpdateParam.getName());
        if (sysDept2 != null && !sysDept2.getId().equals(sysDeptUpdateParam.getId())) {
            throw new BusinessException("同层级不能有相同的部门名称！");
        }
        SysDept sysDept = sysDeptUpdateParamToSysDept(sysDeptUpdateParam);
        sysDeptMapper.update(sysDept);
    }

    private SysDept sysDeptUpdateParamToSysDept(SysDeptUpdateParam sysDeptUpdateParam) {
        SysDept sysDept = new SysDept();
        sysDept.setId(sysDeptUpdateParam.getId());
        sysDept.setParentId(sysDeptUpdateParam.getParentId());
        sysDept.setName(sysDeptUpdateParam.getName());
        sysDept.setLeaderId(sysDeptUpdateParam.getLeaderId());
        sysDept.setSort(sysDeptUpdateParam.getSort());
        sysDept.setRemark(sysDeptUpdateParam.getRemark());
        return sysDept;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void delete(List<Long> ids) {
        if (ObjectUtils.isNotEmpty(ids)) {
            for (Long id : ids) {
                // 1. 如果没有子部门，则查询该部门下是否有员工
                List<SysUser> sysUserList = sysUserMapper.queryByDeptId(id);
                if (!sysUserList.isEmpty()) {
                    SysDept sysDept = sysDeptMapper.queryById(id);
                    throw new BusinessException(String.format("部门:%s下存在员工，无法删除", sysDept.getName()));
                }

                // 2. 删除部门
                sysDeptMapper.deleteById(id);
            }
        }
    }
}
